﻿#include "once_trigger_thread.h"

void OnceTriggerADCThread::start()
{
  thread_is_running_ = true;

  auto base_device = base_device_.lock();
  total_data_length_ = base_device->GetCurrentDataLength();
  data_.resize(base_device->GetADCLegalChannelSize());
  for (int i = 0; i < data_.size(); i++)
  {
    data_[i].reserve(2 * total_data_length_);
  }

  // 超时时间 = 数据长度 / 采样率
  timeout_msec_ = (static_cast<double>(total_data_length_) / base_device->GetCurrentSampleRate() * 1000) + 500;

  // 启动线程
  thread_ = std::thread(&OnceTriggerADCThread::run, this);
}

void OnceTriggerADCThread::quit()
{
  {
    std::lock_guard<std::mutex> lock(mutex_);
    thread_is_running_ = false;
  }
  cv_.notify_one();
  if (thread_.joinable())
  {
    thread_.join();
  }
}

void OnceTriggerADCThread::run()
{
  std::cout << "OnceTriggerADCThread start" << std::endl;
  auto base_device = base_device_;

  // 上次读取数据的时间
  auto buffer_data_time_last = std::chrono::steady_clock::now();

  while (true)
  {
    bool success = ReadADCData();

    {
      std::unique_lock<std::mutex> lock(mutex_);
      if (!thread_is_running_)
      {
        break;
      }
      if (success)
      {
        buffer_data_time_last = std::chrono::steady_clock::now();
      }
      else if (!CheckDataEmpty() &&
               CheckTimeout(buffer_data_time_last, timeout_msec_))
      {
        // 超时默认后面没有数据 发送数据
        std::cout << "发送数据" << std::endl;
        for (auto &i : data_)
        {
          i.clear();
        }
        break;
      }
    }
  }

  std::cout << "OnceTriggerADCThread end" << std::endl;
  thread_is_running_ = false;
}

bool OnceTriggerADCThread::ReadADCData()
{
  bool success = false;
  auto base_device = base_device_.lock();
  const auto channel_number = base_device->GetADCLegalChannel().size();
  
  // 轮流读取各通道中的数据
  for (int i = 0; i < channel_number; i++)
  {
    // 读取到的数据
    float temp_data = 0;
    if (!base_device->TryReadADCData(i, &temp_data))
    {
      // std::cout << "Channel " << i + 1 << "fail to read data" << std::endl;
      continue;
    }

    data_[i].emplace_back(temp_data);
    std::cout << "channel " << i + 1 << " data = " << temp_data << std::endl;

    success = true;
  }

  return success;
}

bool OnceTriggerADCThread::CheckTimeout(const std::chrono::steady_clock::time_point &start, int timeout_msec)
{
  auto diff = std::chrono::steady_clock::now() - start;
  auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(diff);

  return duration.count() >= timeout_msec;
}

bool OnceTriggerADCThread::CheckDataEmpty()
{
  for (auto &i : data_)
  {
    if (!i.empty())
    {
      return false;
    }
  }

  return true;
}

void OnceTriggerADCThread::setThread_is_running(bool newThread_is_running)
{
    thread_is_running_ = newThread_is_running;
}

bool OnceTriggerADCThread::thread_is_running(){
  return thread_is_running_;
}
